package org.iteam.core.shiro;

import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.iteam.core.Constant;
import org.iteam.core.model.sys.SysUser;
import org.iteam.core.service.sys.SysUserService;

public class CustomAuthenticator extends AuthorizingRealm {

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		if (principals == null) {
			throw new AuthorizationException(
					"PrincipalCollection method argument cannot be null.");
		}
		String username = (String) getAvailablePrincipal(principals);
		Set<String> roleNames = getRoleNamesForUser(username);
		Set<String> permissions = getPermissions(username, roleNames);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
		info.setStringPermissions(permissions);
		return info;

	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) authcToken;
		String username = upToken.getUsername();
		AuthenticationInfo info = null;
		if (username == null) {
			throw new AccountException("用户验证错误[用户名为空].");
		}
		try {
			SysUser user = SysUserService.getInstance().show(username);
			if (user == null)
				throw new AccountException("用户验证错误[用户信息不存在].");
			if (!user.getStatus().trim().equalsIgnoreCase("ENABLE"))
				throw new AccountException("用户验证错误[用户已禁用].");
			info = buildAuthenticationInfo(user.getAccount(), user
					.getPassword().toCharArray());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new AccountException("用户验证错误[查询用户信息异常].");
		} catch (Exception e) {
			e.printStackTrace();
			throw new AccountException("用户验证错误[查询用户信息异常].");
		}
		return info;
	}

	protected AuthenticationInfo buildAuthenticationInfo(String username,
			char[] password) {
		return new SimpleAuthenticationInfo(username, password, getName());
	}

	protected Set<String> getRoleNamesForUser(String username) {
		try {
			return SysUserService.getInstance().getRoleNamesForUser(username);
		} catch (Exception e) {
			e.printStackTrace();
			return new LinkedHashSet<String>();
		}
	}

	protected Set<String> getPermissions(String username,
			Collection<String> roleNames) {
		return AuthUtils.getPermissions(SecurityUtils.getSubject().getSession()
				.getAttribute(Constant.SESSION_CURRENT_ROLE_CODE).toString());
	}
}
